package org.linlinjava.litemall.wx.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.RequiredArgsConstructor;
import org.linlinjava.litemall.core.notify.AwsNotifyService;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.util.IpUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.wx.constant.LitemallWXConstants;
import org.linlinjava.litemall.wx.dto.UserInfoDTO;
import org.linlinjava.litemall.wx.dto.WxAppleLoginDTO;
import org.linlinjava.litemall.wx.enums.RegisterTypeEnum;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import static org.linlinjava.litemall.wx.util.WxResponseCode.AUTH_ACCOUNT_SYSTEM_DISABLE;
import static org.linlinjava.litemall.wx.util.WxResponseCode.MOBILE_CODE_ONE;
@Service
@RequiredArgsConstructor
public class WxAuthSerivce {

    private final LitemallUserService userService;
    private final LumierelLevelMemberService lumierelLevelMemberService;
    private final LitemallTokenService litemallTokenService;
    private final NoticeHelper noticeHelper;
    private final AwsNotifyService awsNotifyService;
    private final LitemallGiftCardUserService litemallGiftCardUserService;
    private final LumiereCouponUserService lumiereCouponUserService;
    private final LumierePayMemberUserLogService lumierePayMemberUserLogService;
    private final LumierePayMemberUserService lumierePayMemberUserService;
    private final LumiereSubscribeUserService lumiereSubscribeUserService;

    public Object appleLogin(WxAppleLoginDTO wxAppleLoginDTO, HttpServletRequest request) {
        if(ObjectUtil.isNull(wxAppleLoginDTO)){
            return ResponseUtil.badArgument();
        }

        LitemallUser user = userService.getOne(Wrappers.lambdaQuery(LitemallUser.class)
                .eq(LitemallUser::getAppleId, wxAppleLoginDTO.getUsername())
                .eq(LitemallUser::getInnerAccount, 0)
                .in(LitemallUser::getStatus, 0, 1));
        if(ObjectUtil.isNull(user)){
            int firstDotIndex = wxAppleLoginDTO.getUsername().indexOf(".");
            LitemallUser newuser = new LitemallUser();
            newuser.setAppleId(wxAppleLoginDTO.getUsername());
            newuser.setUsername(String.format("LUc%s",LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)));
            newuser.setEmail(wxAppleLoginDTO.getEmailAddress());
            newuser.setAvatar(LitemallWXConstants.LUMIEREHEAD_APPLE);
            newuser.setNickname("apple_"+wxAppleLoginDTO.getUsername().substring(0,firstDotIndex));
            newuser.setGender((byte) 0);
            newuser.setUserLevel((byte) 0);
            newuser.setStatus((byte) 0);
            newuser.setPoints(new BigDecimal(0));
            newuser.setRegisterType(RegisterTypeEnum.SOCIAL_MEDIA.getCode());
            newuser.setLastLoginTime(LocalDateTime.now());
            newuser.setLastLoginIp(IpUtil.getIpAddr(request));
            //设置会员等级为最基本会员
            LumiereLevelMember lumiereLevelMember = lumierelLevelMemberService.getOne(Wrappers.lambdaQuery(LumiereLevelMember.class)
                    .isNull(LumiereLevelMember::getPid)
                    .eq(LumiereLevelMember::getDeleted, 0)
                    .eq(LumiereLevelMember::getStatus, 2));
            newuser.setUserLevel(lumiereLevelMember.getId().byteValue());
            newuser.setUserLevel(lumiereLevelMember.getId().byteValue());
            String invitedStr = userService.getCharAndNum();
            newuser.setInvitedCode(invitedStr);
            String membershipNumber = IdUtil.objectId();
            newuser.setMembershipNumber(membershipNumber);
            userService.add(newuser);
            //查看是否有注册邮箱对应的礼物卡
            CompletableFuture.runAsync(()->{
                List<LitemallGiftCardUser> cardUsers = litemallGiftCardUserService.findCardUserByUserName(newuser.getUsername());
                if(cardUsers == null){
                    cardUsers = litemallGiftCardUserService.findCardUserByUserName(newuser.getUsername());
                    cardUsers.get(0).setUserId(newuser.getId());
                    litemallGiftCardUserService.updateById(cardUsers.get(0));
                }
            });
            //查看是否有待领取的优惠券
            CompletableFuture.runAsync(()->{
                List<LumiereCouponUser> litemallCouponUsers = lumiereCouponUserService.list(Wrappers.lambdaQuery(LumiereCouponUser.class)
                        .isNull(LumiereCouponUser::getUserId)
                        .eq(LumiereCouponUser::getUserName, newuser.getUsername()));
                litemallCouponUsers.stream().forEach(litemallCouponUser -> {
                    litemallCouponUser.setUserId(newuser.getId());
                });
                lumiereCouponUserService.updateBatchById(litemallCouponUsers);
            });

            //绑定付费会员被赠送记录
            CompletableFuture.runAsync(()->{
                List<LumierePayMemberUserLog> lumierePayMemberUserLogs = lumierePayMemberUserLogService.list(Wrappers.lambdaQuery(LumierePayMemberUserLog.class)
                        .eq(LumierePayMemberUserLog::getPurchaseName, newuser.getUsername())
                        .and(wapper->{
                            wapper.eq(LumierePayMemberUserLog::getUserId, 0)
                                    .or()
                                    .isNull(LumierePayMemberUserLog::getUserId);

                        }));
                lumierePayMemberUserLogs.stream().forEach(lumierePayMemberUserLog -> {
                    lumierePayMemberUserLog.setUserId(newuser.getId());
                });
                lumierePayMemberUserLogService.updateBatchById(lumierePayMemberUserLogs);
            });


            //将别人赠送的礼物卡、订阅、会员等绑定该账号
            CompletableFuture.runAsync(()->{
                List<LitemallGiftCardUser> cardUserByUserName = litemallGiftCardUserService.findCardUserByUserName(newuser.getUsername());
                if(CollUtil.isNotEmpty(cardUserByUserName)){
                    cardUserByUserName.stream().forEach(litemallGiftCardUser -> {
                        //绑定上账号
                        litemallGiftCardUser.setUserId(newuser.getId());
                        litemallGiftCardUserService.updateById2(litemallGiftCardUser);
                    });
                }
            });
            CompletableFuture.runAsync(()->{
                List<LumierePayMemberUser> lumierePayMemberUserList = lumierePayMemberUserService.list(Wrappers.lambdaQuery(LumierePayMemberUser.class)
                        .eq(LumierePayMemberUser::getUserName, newuser.getUsername())
                );
                if(CollUtil.isNotEmpty(lumierePayMemberUserList)){
                    lumierePayMemberUserList.stream().forEach(lumierePayMemberUser -> {
                        lumierePayMemberUser.setUserId(newuser.getId());
                        lumierePayMemberUserService.update(lumierePayMemberUser);
                    });
                }
            });
            CompletableFuture.runAsync(()->{
                List<LumiereSubscribeUser> lumiereSubscribeUserList = lumiereSubscribeUserService.list(Wrappers.lambdaQuery(LumiereSubscribeUser.class)
                        .eq(LumiereSubscribeUser::getUserName, newuser.getUsername())
                );
                if(CollUtil.isNotEmpty(lumiereSubscribeUserList)){
                    lumiereSubscribeUserList.stream().forEach(lumiereSubscribeUser -> {
                        lumiereSubscribeUser.setUserId(newuser.getId());
                        lumiereSubscribeUserService.update(Wrappers.lambdaUpdate(LumiereSubscribeUser.class)
                                .eq(LumiereSubscribeUser::getId,lumiereSubscribeUser.getId())
                                .set(LumiereSubscribeUser::getUserId,newuser.getId())
                        );
                    });
                }
            });
            //发送新人欢迎消息
            noticeHelper.noticeUser(Constants.MSG_TYPE_SYSTEM,LitemallWXConstants.WX_NEWCOMER_TITLE_NOTICEMAIL,LitemallWXConstants.WX_NEWCOMER_NOTICEMAIL,newuser.getId(),newuser);

            // userInfo
            UserInfoDTO userInfo = new UserInfoDTO();
            userInfo.setNickName(newuser.getUsername());
            userInfo.setAvatarUrl(newuser.getAvatar());
            // token
            String token = UserTokenManager.generateToken(newuser.getId());

            //存储token
            LitemallToken litemallToken = LitemallToken.builder()
                    .userId(user.getId()).serve(1)
                    .device(1).validDays(720)
                    .token(token).valid(0)
                    .loginTime(LocalDateTime.now())
                    .loginIp(wxAppleLoginDTO.getLoginIp())
                    .build();
            litemallTokenService.saveOrUpdate(litemallToken);

            Map<Object, Object> result = new HashMap();
            result.put("token", token);
            result.put("userInfo", userInfo);
            return ResponseUtil.ok(result);
        }else {
            //判断他的账号状态
            if(user.getStatus()==1&&!user.getDeletedBy().equals(user.getId())){
                return ResponseUtil.fail(AUTH_ACCOUNT_SYSTEM_DISABLE, "账号已被系统禁用，请联系客服处理");
            }
            //如果是用户自己注销的账号就自动解禁
            if(user.getStatus()==1&&user.getDeletedBy().equals(user.getId())){
                user.setStatus((byte) 0);
                user.setDeleted(false);
            }
            //如果没有基础会员等级就给予
            if(user.getInnerAccount()&&(user.getUserLevel()==null||user.getUserLevel()==0)){
                LumiereLevelMember lumiereLevelMember = lumierelLevelMemberService.getOne(Wrappers.lambdaQuery(LumiereLevelMember.class)
                        .isNull(LumiereLevelMember::getPid)
                        .eq(LumiereLevelMember::getDeleted, 0)
                        .eq(LumiereLevelMember::getStatus, 2));
                user.setUserLevel(lumiereLevelMember.getId().byteValue());
            }
            // 更新登录情况
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtil.getIpAddr(request));
            userService.updateById2(user);

            // userInfo
            UserInfoDTO userInfo = new UserInfoDTO();
            userInfo.setNickName(wxAppleLoginDTO.getUsername());
            userInfo.setAvatarUrl(user.getAvatar());

            // token
            String token = UserTokenManager.generateToken(user.getId());

            squeezeDown(user,token,wxAppleLoginDTO.getLoginIp());
            Map<Object, Object> result = new HashMap();
            result.put("token", token);
            result.put("userInfo", userInfo);
            return ResponseUtil.ok(result);
        }
    }


    //踢人下线
    public void squeezeDown(LitemallUser user,String token,String loginIp){
        //存储token
        LitemallToken litemallToken = LitemallToken.builder()
                .userId(user.getId()).serve(1)
                .device(1).validDays(720)
                .token(token).valid(0)
                .loginTime(LocalDateTime.now())
                .loginIp(loginIp)
                .build();
        List<LitemallToken> litemallTokens = litemallTokenService.list(Wrappers.lambdaQuery(LitemallToken.class)
                .eq(LitemallToken::getUserId, user.getId())
                .eq(LitemallToken::getValid, 0));
        if(litemallTokens.size()>0){
            litemallTokens.stream().forEach(litemallToken1 -> litemallToken1.setValid(1));
            //有另一端登陆 「等待确认踢人下线」
            litemallTokenService.updateBatchById(litemallTokens);
            //发送系统通知
            noticeHelper.noticeUser(Constants.MSG_TYPE_SYSTEM, LitemallWXConstants.WX_MUTUAL_TITLE_NOTICEHELPER,LitemallWXConstants.WX_MUTUAL_NOTICEHELPER,user.getId(),user);
            //发送短信通知
            if(StrUtil.isNotBlank(user.getMobile())){
                awsNotifyService.sendSms(MOBILE_CODE_ONE+user.getMobile(),LitemallWXConstants.WX_MUTUAL_NOTICEHELPER,Constants.AWS_MESSAGE_TYPE_TRANSACTIONAL);
            }
        }
        litemallTokenService.save(litemallToken);
    }

}
